<?php
namespace app\common;

use app\common\DB;

abstract class Model
{
    abstract public function policyId();
    
    abstract public function table();
    
    private static $models = [];
    
    private static $facades = [];
    
    private function __construct()
    {
        if (count(self::$facades) === 0)
        {
            $dbMethods = get_class_methods(DB::class);
            self::$facades = array_fill_keys($dbMethods, 1);
        }
    }
    
    private function __clone()
    {
        
    }
    
    public static function model()
    {
        $className = get_called_class();
        if (isset(self::$models[$className]))
        {
            return self::$models[$className];
        }
        return self::$models[$className] = new static;
    }
    
    public function __call($method, $args)
    {
        return self::dispatchFacadeCall($method, $args);
    }
    
    public static function __callstatic($method, $args)
    {
        return self::dispatchFacadeCall($method, $args);
    }
    
    private static function dispatchFacadeCall($method, $args)
    {
        if (!empty(self::$facades[$method]))
        {
            $obj = self::model();
            $policyId = $obj->policyId();
            $table = $obj->table();
            //查询类，若指定要获取对象，添加object参数，默认返回数组
            if (in_array($method, ['getById', 'select']) && isset($args[0]['object']) && $args[0]['object'])
            {
                $args[0]['object'] = get_called_class();
            }
            return call_user_func_array([DB::connect($policyId)->table($table), $method], $args);
        }
        else
        {
            throw new \OutOfBoundsException(sprintf("method: '%s' is not valid in '%s'", $method, get_called_class()));
        }
    }
}